<?php


namespace models\Business;


use models\Exception\Business\AnnounceException;
use models\Exception\Business\AnnouncestatsException;
use models\Exception\Business\MemberException;
use models\Exception\DAO\ModelDriverException;
use models\Exception\DAO\ModelException;
use models\Exception\DAO\ModelReflectionException;
use models\Exception\DAO\ModelSqlException;
use models\Exception\Service\ServiceException;
use models\Exception\Transformer\TransformerException;
use models\Service\AnnounceService;
use models\Service\AnnouncestatsService;
use models\Service\MemberService;
use Yaf\Registry;
use models\Business\JPush;

class Announce
{
    /**
     * 查询系统消息的推送状态
     * @param int $announce_id
     * @return bool
     * @throws AnnounceException
     * @throws MemberException
     * @throws ModelDriverException
     * @throws ModelException
     * @throws ModelReflectionException
     * @throws ModelSqlException
     * @throws ServiceException
     * @throws TransformerException
     */
    static public function chkPushStatus($announce_id = 0) {
        try {
            if (empty($announce_id))
                throw new AnnounceException(AnnounceException::ANNOUNCE_ID_IS_EMPTY, AnnounceException::ANNOUNCE_ID_IS_EMPTY_NO);

            $announce_exists = AnnounceService::getInstance()->getOne($announce_id);
            if (empty($announce_exists))
                throw new AnnounceException(AnnounceException::ANNOUNCE_IS_NOT_EXISTS, AnnounceException::ANNOUNCE_IS_NOT_EXISTS_NO);
            if ($announce_exists['is_push'] == 0)
                throw new AnnounceException(AnnounceException::ANNOUNCE_NOT_PUSH, AnnounceException::ANNOUNCE_NOT_PUSH_NO);

            $member = MemberService::getInstance()->getOne($announce_exists['member_id']);
            if (empty($member))
                throw new MemberException(MemberException::MEMBER_IS_NOT_EXISTS, MemberException::MEMBER_IS_NOT_EXISTS_NO);

            return JPush::getStatus((int)$announce_exists['msg_id'], $member['registration_id']);
        } catch (MemberException $e) {
            throw $e;
        } catch (AnnounceException $e) {
            throw $e;
        }
    }

    /**
     * 阅读消息
     * @param array $parameters
     * @throws AnnounceException
     * @throws AnnouncestatsException
     * @throws ModelDriverException
     * @throws ModelException
     * @throws ModelReflectionException
     * @throws ModelSqlException
     * @throws ServiceException
     * @throws TransformerException
     */
    static public function readAnnounce($parameters = []) {

        try {
            $announce_exists = AnnounceService::getInstance()->getOne($parameters['id']);

            if (empty($announce_exists))
                throw new AnnounceException(AnnounceException::ANNOUNCE_IS_NOT_EXISTS, AnnounceException::ANNOUNCE_IS_NOT_EXISTS_NO);
            if ($announce_exists['member_id'] != 0 && $announce_exists['member_id'] != Registry::get('jwt_info')->id)
                throw new AnnounceException(AnnounceException::ANNOUNCE_INVALID, AnnounceException::ANNOUNCE_INVALID_NO);

            // $announce_id = 0, $member_id = 0,
            AnnouncestatsService::getInstance()->create($parameters['id'], Registry::get('jwt_info')->id);

        } catch (AnnounceException $e) {
            throw $e;
        } catch (ModelDriverException $e) {
            if ($e->getCode() == ModelDriverException::DRIVER_EXCEPTION_MSG_NO)
                throw new AnnouncestatsException(AnnouncestatsException::ANNOUNCE_READ_FAILURE, AnnouncestatsException::ANNOUNCE_READ_FAILURE_NO);
            throw $e;
        } catch (ModelException $e) {
            throw $e;
        } catch (ModelReflectionException $e) {
            throw $e;
        } catch (ModelSqlException $e) {
            throw $e;
        } catch (TransformerException $e) {
            throw $e;
        }
    }

    /**
     * 编辑
     * @param array $parameters
     * @return array|mixed|null
     * @throws AnnounceException
     * @throws MemberException
     * @throws ModelDriverException
     * @throws ModelException
     * @throws ModelReflectionException
     * @throws ModelSqlException
     * @throws ServiceException
     * @throws TransformerException
     */
    static public function edit($parameters = []) {
        try {
            if (! isset($parameters['id']) || empty($parameters['id']))
                throw new AnnounceException(AnnounceException::ANNOUNCE_ID_IS_EMPTY, AnnounceException::ANNOUNCE_ID_IS_EMPTY_NO);

            $update_arr = [];
            if (isset($parameters['title']))
                $update_arr['title'] = $parameters['title'];
            if (isset($parameters['stats']))
                $update_arr['stats'] = $parameters['stats'];
            if (isset($parameters['content']))
                $update_arr['content'] = $parameters['content'];
            if (isset($parameters['type']))
                $update_arr['type'] = $parameters['type'];
            if (isset($parameters['is_push']))
                $update_arr['is_push'] = $parameters['is_push'];
            if (isset($parameters['mobile'])) {
                if ($parameters['mobile'] != 0) {
                    $member = MemberService::getInstance()->getOne(['groupOp' => 'AND', 'rules' => [
                        ['field' => 'mobile', 'op' => 'eq', 'data' => $parameters['mobile']]]]);
                    if (! empty($member))
                        $update_arr['member_id'] = $member['id'];
                    else
                        throw new MemberException(MemberException::MEMBER_IS_NOT_EXISTS, MemberException::MEMBER_IS_NOT_EXISTS_NO);
                } else
                    $update_arr['member_id'] = 0;
            }

            if (!empty($update_arr)) {
                $update_arr['updated_at'] = date('Y-m-d H:i:s', time());
                $update_arr['updated_by'] = Registry::get('jwt_info')->id;

                $announce = AnnounceService::getInstance()->update($update_arr, $parameters['id']);

            } else
                $announce = AnnounceService::getInstance()->getOne($parameters['id']);

            // 极光推送
            if (isset($update_arr['is_push']) && $update_arr['is_push'] == 1) {

            }

            return $announce;
        } catch (AnnounceException $e) {
            throw $e;
        } catch (ModelDriverException $e) {
            if ($e->getCode() == ModelDriverException::DRIVER_EXCEPTION_MSG_NO)
                throw new AnnounceException(AnnounceException::ANNOUNCE_EDIT_FAILURE, AnnounceException::ANNOUNCE_EDIT_FAILURE_NO);
            throw $e;
        } catch (ModelException $e) {
            throw $e;
        } catch (ModelReflectionException $e) {
            throw $e;
        } catch (ModelSqlException $e) {
            throw $e;
        } catch (ServiceException $e) {
            throw $e;
        } catch (TransformerException $e) {
            throw $e;
        }

    }

    /**
     * 获取指定用户的消息
     * @param array $parameters
     * @return array|mixed
     * @throws AnnounceException
     * @throws ModelDriverException
     * @throws ModelException
     * @throws ModelReflectionException
     * @throws ModelSqlException
     * @throws ServiceException
     * @throws TransformerException
     */
    static public function getMyAnnounceList($parameters = []) {
        try {
            $condition = ['groupOp' => 'AND', 'rules' => [
                ['field' => 'stats', 'op' => 'eq', 'data' => 1],
                ['field' => 'member_id', 'op' => 'in', 'data' => implode(',', [Registry::get('jwt_info')->id, 0])]
            ]];
            $announce = AnnounceService::getInstance()->getList(
                isset($parameters['page']) ? $parameters['page'] : 1,
                isset($parameters['page_size']) ? $parameters['page_size'] : 10,
                isset($parameters['sort']) ? $parameters['sort'] : 'desc',
                isset($parameters['order']) ? $parameters['order'] : 'id',
                $condition
            );
            if (empty($announce))
                throw new AnnounceException(AnnounceException::ANNOUNCE_IS_NOT_EXISTS, AnnounceException::ANNOUNCE_IS_NOT_EXISTS_NO);

            $stats = AnnouncestatsService::getInstance()->getList(1, count($announce['data']), 'desc', 'id',
                ['groupOp' => 'AND', 'rules' => [
                    ['field' => 'member_id', 'op' => 'eq', 'data' => Registry::get('jwt_info')->id],
                    ['field' => 'announce_id', 'op' => 'in', 'data' => implode(',', array_column($announce['data'], 'id'))]
                ]]);
            $stats_id_arr = array_column($stats['data'], 'id', 'announce_id');

            foreach ($announce['data'] as $idx => $announce_info) {
                $announce['data'][$idx]['is_read'] = (int)isset($stats_id_arr[$announce_info['id']]);
            }

            return $announce;
        } catch (AnnounceException $e) {
            throw $e;
        } catch (ModelDriverException $e) {
            throw $e;
        } catch (ModelException $e) {
            throw $e;
        } catch (ModelReflectionException $e) {
            throw $e;
        } catch (ModelSqlException $e) {
            throw $e;
        } catch (ServiceException $e) {
            throw $e;
        } catch (TransformerException $e) {
            throw $e;
        }
    }

    /**
     * @param array $parameters
     * @return array|mixed
     * @throws MemberException
     * @throws ModelDriverException
     * @throws ModelException
     * @throws ModelReflectionException
     * @throws ModelSqlException
     * @throws ServiceException
     * @throws TransformerException
     */
    static public function getAnnounceList($parameters = []) {
        try {
            $rules = $condition = [];
            if (isset($parameters['type']))
                array_push($rules, ['field' => 'type', 'op' => 'eq', 'data' => $parameters['type']]);

            if (isset($parameters['is_push']))
                array_push($rules, ['field' => 'is_push', 'op' => 'eq', 'data' => $parameters['is_push']]);

            if (isset($parameters['stats']))
                array_push($rules, ['field' => 'stats', 'op' => 'eq', 'data' => $parameters['stats']]);

            if (isset($parameters['title']))
                array_push($rules, ['field' => 'title', 'op' => 'nc', 'data' => $parameters['title'] . '%']);

            $member_id_arr = [];
            if (isset($parameters['mobile'])) {
                $member = MemberService::getInstance()->getList(1, 999, 'desc', 'id', ['groupOp' => 'AND', 'rules' => [
                    ['field' => 'mobile', 'op' => 'nc', 'data' => $parameters['mobile'] . '%']]]);
                if (! empty($member['data']))
                    $member_id_arr = array_column($member['data'], 'id');
                else
                    throw new MemberException(MemberException::MEMBER_IS_NOT_EXISTS, MemberException::MEMBER_IS_NOT_EXISTS_NO);
            }

            if (isset($parameters['nickname'])) {
                $member = MemberService::getInstance()->getList(1, 999, 'desc', 'id', ['groupOp' => 'AND', 'rules' => [
                    ['field' => 'nickname', 'op' => 'nc', 'data' => $parameters['nickname'] . '%']]]);
                if (! empty($member['data']))
                    $member_id_arr = empty($member_id_arr) ? array_column($member['data'], 'id') :
                        array_merge($member_id_arr, array_column($member['data'], 'id'));
                else
                    throw new MemberException(MemberException::MEMBER_IS_NOT_EXISTS, MemberException::MEMBER_IS_NOT_EXISTS_NO);
            }

            if (!empty($member_id_arr))
                array_push($rules, ['field' => 'member_id', 'op' => 'in', 'data' => implode(',', $member_id_arr)]);

            if (isset($parameters['start_created_at']))
                array_push($rules, ['field' => 'created_at', 'op' => 'ge', 'data' => date("Y-m-d 00:00:00", strtotime(str_replace('/', '-', $parameters['start_created_at'])))]);

            if (isset($parameters['end_created_at']))
                array_push($rules, ['field' => 'created_at', 'op' => 'le', 'data' => date("Y-m-d 23:59:59", strtotime(str_replace('/', '-', $parameters['end_created_at'])))]);


            if (!empty($rules))
                $condition = ['groupOp' => 'AND', 'rules' => $rules];

            $announce = AnnounceService::getInstance()->getList(
                isset($parameters['page']) ? $parameters['page'] : 1,
                isset($parameters['page_size']) ? $parameters['page_size'] : 10,
                isset($parameters['sort']) ? $parameters['sort'] : 'desc',
                isset($parameters['order']) ? $parameters['order'] : 'id',
                $condition
            );

            if (isset($parameters['from_api']) && $parameters['from_api'] === true && !empty($announce)) {
                $stats = AnnouncestatsService::getInstance()->getList(1, count($announce['data']), 'desc', 'id',
                    ['groupOp' => 'AND', 'rules' => [
                        ['field' => 'member_id', 'op' => 'eq', 'data' => Registry::get('jwt_info')->id],
                        ['field' => 'announce_id', 'op' => 'in', 'data' => implode(',', array_column($announce['data'], 'id'))]
                    ]]);
                $stats_id_arr = array_column($stats['data'], 'id', 'announce_id');

                foreach ($announce['data'] as $idx => $announce_info) {
                    $announce['data'][$idx]['is_read'] = (int)isset($stats_id_arr[$announce_info['id']]);
                }
            } else
                $announce = User::getUsersByModule($announce);

            $announce = Member::getMembersByModules($announce, false);

            return $announce;
        } catch (ModelDriverException $e) {
            throw $e;
        } catch (ModelException $e) {
            throw $e;
        } catch (ModelReflectionException $e) {
            throw $e;
        } catch (ModelSqlException $e) {
            throw $e;
        } catch (ServiceException $e) {
            throw $e;
        } catch (TransformerException $e) {
            throw $e;
        }

    }

    /**
     * @param array $parameters
     * @return array
     * @throws AnnounceException
     * @throws MemberException
     * @throws ModelDriverException
     * @throws ModelException
     * @throws ModelReflectionException
     * @throws ModelSqlException
     * @throws ServiceException
     * @throws TransformerException
     */
    static public function create($parameters = []) {
        try {
            $date_now = date('Y-m-d H:i:s', time());

            if (isset($parameters['mobile']) && ! isset($parameters['mobile_id'])) {
                $member = MemberService::getInstance()->getOne(['groupOp' => 'AND', 'rules' => [
                    ['field' => 'mobile', 'op' => 'nc', 'data' => $parameters['mobile']]]]);
                if (empty($member))
                    throw new MemberException(MemberException::MEMBER_IS_NOT_EXISTS, MemberException::MEMBER_IS_NOT_EXISTS_NO);
                else
                    $parameters['member_id'] = $member['id'];
            } else if (isset($parameters['member_id']) && ! isset($parameters['mobile'])) {
                $member = MemberService::getInstance()->getOne($parameters['member_id']);
                if (empty($member))
                    throw new MemberException(MemberException::MEMBER_IS_NOT_EXISTS, MemberException::MEMBER_IS_NOT_EXISTS_NO);
            }


            // $type = 0, $member_id = 0, $title = "",
            // $content = "", $stats = 0, $is_push = 0,
            // $created_at = "", $created_by = 0, $updated_at = "", $updated_by = 0
            $announce = AnnounceService::getInstance()->create(
                $parameters['type'], $parameters['member_id'], $parameters['title'],
                $parameters['content'], $parameters['stats'], isset($parameters['is_push']) ? $parameters['is_push'] : 0,
                $date_now, Registry::get('jwt_info')->id, $date_now, Registry::get('jwt_info')->id
            );

            // 极光推送
            if (isset($parameters['is_push']) && $parameters['is_push'] == 1) {

            }

            return $announce;
        } catch (MemberException $e) {
            throw $e;
        } catch (ModelDriverException $e) {
            if ($e->getCode() == ModelDriverException::DRIVER_EXCEPTION_MSG_NO)
                throw new AnnounceException(AnnounceException::ANNOUNCE_CREATE_FAILURE, AnnounceException::ANNOUNCE_CREATE_FAILURE_NO);
            throw $e;
        } catch (ModelException $e) {
            throw $e;
        } catch (ModelReflectionException $e) {
            throw $e;
        } catch (ModelSqlException $e) {
            throw $e;
        } catch (TransformerException $e) {
            throw $e;
        }
    }

}
